home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / library / trap.s < prev    next >
Text File  |  1994-08-19  |  13KB  |  489 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: trap.s,v 1.1 1994/06/19 15:17:35 rluebbert Exp $
  21.  *
  22.  *  $Log: trap.s,v $
  23. # Revision 1.1  1994/06/19  15:17:35  rluebbert
  24. # Initial revision
  25. #
  26.  */
  27.     .globl    _trap_00
  28.     .globl    _restore_00
  29.     .globl    _sup00_do_sigreturn
  30.     .globl    _sup00_do_sigreturn_ssp
  31.     .globl    _trap_20
  32.     .globl    _restore_20
  33.     .globl    _sup20_do_sigreturn
  34.     .globl    _sup20_do_sigreturn_ssp
  35.     .globl    _supervisor
  36.     .globl    _do_sigreturn
  37.     .globl    _launch_glue
  38.     .globl    _addupc
  39.     .globl    _resetfpu
  40.  
  41. #undef DEBUG
  42.  
  43.     |
  44.     | ATTENTION:
  45.     | 
  46.     | do_sigreturn() uses absolute offsets into struct user.
  47.     | if you change struct user, be sure to check whether the current
  48.     | offsets of p_sigmask and u_onstack are still valid !!!!
  49.     |
  50.  
  51.  
  52.     | This is the trap processing function for the mc68000.
  53.     | Things are quite easy here, just save the general purpose registers
  54.     | and the pc/sr combo, call trap(), then restore the previous
  55.     | context and return
  56. _trap_00:
  57.     movel    a5,sp@-        | need a scratch register
  58.     movel    usp,a5        | get usp
  59.     moveml    d0-d7/a0-a6,a5@-| store registers on usp
  60.     movel    sp@+,a5@(0x34)    | insert the saved a5 into the saveset
  61.     movel    sp@+,d2        | remember trapnumber
  62.     movew    sp@+,a5@-    | copy SR
  63.     movel    sp@+,a0        | remember and
  64.     movel    a0,a5@-        | copy offending PC
  65.  
  66.     |
  67.     | pass return address and ssp-value on userstack
  68.     | This happens for the same reason as we have a glue_launch entry.
  69.     | trap cleans up these 8 bytes on the user stack itself
  70.     movel    sp,a5@-
  71.     movel    #_restore_00,a5@-
  72.     movel    a5,usp        | and remember current value of usp (a5)
  73.  
  74.     | fine, now process this trap. This might (doesn't have to) push
  75.     | additional frames. If not, we just return where the exception 
  76.     | took place (and probably will again...)
  77.  
  78.     movel    a0,sp@-        | pass offending address (don't know more about it)
  79.     addl    d2,d2        | convert the passed trap number into a fake
  80.     addl    d2,d2        | 68020 frame format word
  81.     movel    d2,sp@-        | and pass it as argument
  82.     jsr    _trap        | to the higher level C trap 
  83.     lea    sp@(8),sp    | processor
  84.  
  85. _restore_00:
  86.     movel    usp,a5        | get usp
  87.     lea    a5@(0x42),a1    | skip over the now no longer needed frame
  88.     movel    a1,usp        | -> 15 registers, one PC and one SR
  89.     
  90.     | set up the original supervisor stack frame
  91.     movel    a5@+,sp@-    | PC
  92.     movew    a5@+,sp@-    | SR
  93.     moveml    a5@,d0-d7/a0-a6    | and the other cpu registers
  94.     rte
  95.  
  96.  
  97.  
  98.     | This is the trap processor for the mc68020 and above, paired with
  99.     | an fpu (don't *need* an fpu though).
  100.     | What is done: start is same as with 68000, but then the complete
  101.     | additional exception frame is saved on the usp, together with the
  102.     | fpu state. Then trap() is called, and then the previous context
  103.     | is restored (involves copying back the frame from the usp over to the ssp)
  104. _trap_20:
  105.     movel    a5,sp@        | nuke the trap number, we use the frame format word
  106.     movel    usp,a5        | get usp
  107.     moveml    d0-d7/a0-a6,a5@-| store registers on usp
  108.     movel    sp@+,a5@(0x34)    | insert the saved a5 into the saveset
  109.     movew    sp@+,a5@-    | copy SR
  110.     movel    sp@+,d2        | remember and
  111.     movel    d2,a5@-        | copy (offending?) PC
  112.  
  113.     | find out more about the frame (according to the MC68030 user manual)
  114.     clrl    d1
  115.     movew    sp@+,d1        | remember frame format word
  116.     movew    d1,d0
  117.     andw    #0xf000,d0
  118.     beq    Lfmt_S0        | S0
  119.     cmpw    #0x1000,d0
  120.     beq    Lfmt_S1        | S1 this (interrupt) frame shouldn't be here...
  121.     cmpw    #0x2000,d0
  122.     beq    Lfmt_S2        | CHK{2},cpTRAPcc,TRAPV,Trace,Div0,MMUcfg,cp post instr
  123.     cmpw    #0x9000,d0
  124.     beq    Lfmt_S9        | cp mid instr,main det prot viol,int during cp instr
  125.     cmpw    #0xa000,d0
  126.     beq    Lfmt_SA_SB    | address or bus error, short and long frame
  127.     cmpw    #0xb000,d0
  128.     bne    Lfmt_S0        | ??? frame, this will probably not fully cleanup sp..
  129.  
  130. Lfmt_SA_SB:
  131.     | this part (upto Lbe10) inspired by locore.s in sys/hp300/ of BSD4.3-reno
  132.     movew    sp@(2),d0    | grab SSW for fault processing
  133.     btst    #12,d0        | RB set?
  134.     beq    LbeX0        | no, test RC
  135.     bset    #14,d0        | yes, must set FB
  136.     movew    d0,sp@(2)    | for hardware too
  137. LbeX0:
  138.     btst    #13,d0        | RC set?
  139.     beq    LbeX1        | no, skip
  140.     bset    #15,d0        | yes, must set FC
  141.     movew    d0,sp@(2)    | for hardware too
  142. LbeX1:
  143.     btst    #8,d0        | data fault?
  144.     beq    Lbe0        | no, check for hard cases
  145.     movel    sp@(8),d2    | fault address is as given in frame
  146.     bra    Lbe10        | thats it
  147. Lbe0:
  148.     btst    #12,d1        | long (type B) stack frame?
  149.     bne    Lbe4        | yes, go handle
  150.     btst    #14,d0        | no, can use saved PC. FB set?
  151.     beq    Lbe3        | no, try FC
  152.     addql    #4,d2        | yes, adjust address
  153.     bra    Lbe10        | done
  154. Lbe3:
  155.     btst    #15,d0        | FC set?
  156.     beq    Lbe10        | no, done
  157.     addql    #2,d2        | yes, adjust address
  158.     bra    Lbe10        | done
  159. Lbe4:
  160.     movel    sp@(28),d2    | long format, use stage B address
  161.     btst    #15,d0        | FC set?
  162.     beq    Lbe10        | no, all done
  163.     subql    #2,d2        | yes, adjust address
  164. Lbe10:
  165.  
  166.     | now move the frame over to the usp (6/21 longwords remain)
  167.     
  168.     moveml    sp@+,d3-d7/a0    | may trash as many registers as I like, I saved
  169.     moveml    d3-d7/a0,a5@-    | them already ;-) First copy 6 longs
  170.  
  171.     btst    #12,d1        | long (type B) stack frame?
  172.     beq    Lfmt_S0        | nope, done
  173.  
  174.     moveml    sp@+,d3-d7/a0-a2 | first copy 8 longs
  175.     moveml    d3-d7/a0-a2,a5@-
  176.     moveml    sp@+,d3-d7/a0-a1 | plus 7 gives 15, plus already stored 6 is 21
  177.     moveml    d3-d7/a0-a1,a5@-
  178.     bra    Lfmt_S0        | finito
  179.  
  180. Lfmt_S9:
  181.     movel    sp@+,a5@-    | S9 is an S2 plus 4 internal (word length) registers
  182.     movel    sp@+,a5@-    | so store those registers, and fall into S2
  183.  
  184. Lfmt_S2:
  185.     movel    sp@+,d2        | S2 contains the offending instruction address
  186.                 | and the frame format word
  187.     movel    d2,a5@-        | we have the offending instruction address here
  188.  
  189.     | fall into
  190.  
  191. Lfmt_S0:
  192. Lfmt_S1:
  193.     movew    d1,a5@-        | and as the last thing store the frame format word
  194.  
  195.     |
  196.     | now lets look at the fpu, if there is an fpu in the system
  197.     |
  198.     
  199.     btst    #4,(4)@(0x129)    | is AFB_68881 set in SysBase->AttnFlags ??
  200.     beq    Lno_fpu
  201.     fsave    a5@-        | dump the fpu state onto the usp
  202.     moveb    a5@,d0        | and get the fpu state identifier
  203.     beq    Lno_fpu        | null frame?
  204.  
  205.     clrl    d0
  206.     moveb    a5@(1),d0    | load state frame size
  207.     bset    #3,a5@(d0)    | set bit 27 of BIU
  208.  
  209.     fmovemx    fp0-fp7,a5@-        | push the fpu data registers and
  210.     fmoveml    fpcr/fpsr/fpi,a5@-    | fpu control registers
  211.  
  212.     movew    #-1,a5@-    | mark that there is fpu stuff on the stack
  213. Lno_fpu:
  214.  
  215.     |
  216.     | pass return address and ssp-value on userstack
  217.     | This happens for the same reason as we have a glue_launch entry.
  218.     | trap cleans up these 8 bytes on the user stack itself
  219.     movel    sp,a5@-
  220.     movel    #_restore_20,a5@-
  221.  
  222.     movel    a5,usp        | set the new value of the usp
  223.  
  224.     | that's it, phew.. now process this frame, and perhaps throw some
  225.     | frames on it as well to deal with the signal
  226.     
  227.     movel    d2,sp@-        | pass offending PC
  228.     movel    d1,sp@-        | pass frame format word
  229.     jsr    _trap        | do distribution in C ;-)
  230.     lea    sp@(8),sp
  231.  
  232. _restore_20:
  233.     |
  234.     | restore the saved stack frame from the usp, and copy the necessary
  235.     | parts over to the ssp
  236.     |
  237.  
  238.     movel    usp,a5
  239.     
  240.     | first deal with fpu stuff, if there's an fpu
  241.  
  242.     btst    #4,(4)@(0x129)    | is AFB_68881 set in SysBase->AttnFlags ??
  243.     beq    Lno_fpu2
  244.     tstb    a5@
  245.     beq    Lrst_fpu_frame    | there's only the null frame, go and restore it
  246.  
  247.     lea    a5@(2),a5    | skip fpu indicator
  248.     fmoveml    a5@+,fpcr/fpsr/fpi    | restore fpu control and
  249.     fmovemx    a5@+,fp0-fp7        | fpu data registers
  250.     
  251. Lrst_fpu_frame:
  252.     frestore a5@+        | and restore the internal fpu state
  253. Lno_fpu2:
  254.     movew    a5@+,d1        | get frame format word
  255.     movew    d1,d0
  256.     andw    #0xf000,d0
  257.     beq    Lrfmt_S0    | S0
  258.     cmpw    #0x1000,d0
  259.     beq    Lrfmt_S1    | S1
  260.     cmpw    #0x2000,d0
  261.     beq    Lrfmt_S2    | S2
  262.     cmpw    #0x9000,d0
  263.     beq    Lrfmt_S9    | S9
  264.     cmpw    #0xa000,d0
  265.     beq    Lrfmt_SA    | SA
  266.     cmpw    #0xb000,d0
  267.     bne    Lrfmt_S0    | ??? frame
  268.  
  269. Lrfmt_SB:
  270.     moveml    a5@+,d3-d7/a0-a2
  271.     moveml    d3-d7/a0-a2,sp@-
  272.     moveml    a5@+,d3-d7/a0-a1
  273.     moveml    d3-d7/a0-a1,sp@- | copy 15 longs
  274.  
  275. Lrfmt_SA:
  276.     movel    a5@+,sp@-    | copy  3 longs
  277.     movel    a5@+,sp@-
  278.     movel    a5@+,sp@-
  279.     
  280. Lrfmt_S9:
  281.     movel    a5@+,sp@-    | copy  2 longs
  282.     movel    a5@+,sp@-
  283.  
  284. Lrfmt_S2:
  285.     movel    a5@+,sp@-    | copy  1 long
  286.  
  287. Lrfmt_S1:
  288. Lrfmt_S0:
  289.     movew    d1,sp@-        | insert frame format word
  290.     movel    a5@+,sp@-    | copy PC
  291.     movew    a5@+,sp@-    | and SR
  292.     
  293.     lea    a5@(0x3c),a1    | skip the rest of the frame
  294.     movel    a1,usp        | 0x3c -> 15 registers
  295.     
  296.     moveml    a5@,d0-d7/a0-a6    | restore the cpu registers
  297.     rte            | that's it (finally) .. 
  298.  
  299.  
  300.     |
  301.     | jump to the given argument in supervisor mode
  302.     | does NOT return
  303.     |
  304. _supervisor:
  305.     movel    sp@(4),a5    | where to go in supervisor
  306.     movel    sp@(8),sp@-    | with this usp
  307.     movel    a6,sp@-
  308.     movel    4:w,a6
  309.     jmp    a6@(-0x1e)    | do it (Supervisor() system call)
  310.  
  311.  
  312.     |
  313.     | restore signal context
  314.     | argument comes in usp
  315.     |
  316.     | mc68020 entry
  317. _sup20_do_sigreturn_ssp:    | entry via jsr from supervisor mode
  318.     movel    sp@(4),sp    | set ssp
  319. _sup20_do_sigreturn:
  320.     lea    sp@(-8),sp    | make room for an exception frame
  321.     movew    #0x20,sp@(6)    | fake format word
  322.     bra    fromsup_sigreturn
  323.  
  324.     | mc68000 entry
  325. _sup00_do_sigreturn_ssp:
  326.     movel    sp@(4),sp    | set ssp
  327. _sup00_do_sigreturn:
  328.     lea    sp@(-6),sp    | make room for an exception frame
  329.  
  330. fromsup_sigreturn:
  331.     moveml    d0/d1/a0/a1,sp@-
  332.  
  333.     movel    usp,a0        | get signal context
  334.     bra    resume_sigreturn
  335.  
  336.     | fall into _do_sigreturn
  337.  
  338.  
  339.     | Supervisor() entry (already comes on exception frame)
  340. _do_sigreturn:
  341.     | make the sigreturn() function preserve all registers
  342.     moveml    d0/d1/a0/a1,sp@-
  343.  
  344.     movel    usp,a0        | get signal context
  345.     movel    a0@+,a6        | restore the trashed a6 register
  346.     movel    a0@,a0
  347.  
  348. resume_sigreturn:
  349.  
  350.  
  351.     movel    4:w,a1        | SysBase
  352.     movel    a1,d1        | remember for later setting of sc_ap
  353.     movel    a1@(0x114),a1    | ThisTask
  354.     movel    a1@(0x2e),a1    | TrapData -> (struct user *)
  355.     
  356.     | ok, now a0:sc, a1:u
  357.  
  358.     | get those offsets in struct user with `print_user.c' !
  359.     movel    a0@+,a1@(0x11c)    | u.u_onstack = sc->sc_onstack
  360.     movel    a0@+,a1@(0x134)    | u.p_sigmask = sc->sc_mask
  361.     movel    a0@+,a1        | usp = sc->sc_sp
  362.     movel    a1,usp
  363.     movel    a0@+,a5        | fp  = sc->sc_fp
  364.  
  365.  
  366.  
  367.     movel    d1,a1        | get back SysBase
  368.     movel    a1@(0x114),a1    | ThisTask
  369.     movel    a0@,a1@(0x0e)    | store Flags,State,IDNestCnt,TDNestCnt
  370.     movel    d1,a1
  371.     lea    a0@(2),a0    | skip unused part of sc_ap
  372.     movew    a0@+,d1        | get IDNestCnt and TDNestCnt
  373.     movew    d1,a1@(0x126)    | store them in SysBase
  374.     tstb    a1@(0x126)
  375.     bmi    Lenable
  376. Ldisabled:
  377.     movew    #0x4000,0xdff09a    | disable interrupts
  378.     bra    Lint_twiddle
  379. Lenable:
  380.     movew    #0xc000,0xdff09a    | enable interrupts
  381. Lint_twiddle:
  382.  
  383.  
  384.     | set pc and sr in current exception frame
  385.     movel    a0@+,sp@(2+4*4)    | set PC
  386.     movew    a0@(2),sp@(4*4)    | and SR
  387.     moveml    sp@+,d0/d1/a0/a1
  388.     rte
  389.  
  390.  
  391.  
  392.     |
  393.     | launch_glue is used to invoke the sig_launch handler. We have to care to
  394.     | clean the supervisor stack, if we should call a signal handler from
  395.     | the launch handler.
  396.     | The bad thing is, that doing this right needs information on how 
  397.     | the tc_Launch entry is called from the OS. Thus I pass two parameters
  398.     | on the user stack, the value of the `virgin' ssp and the value of
  399.     | a4, which happens to contain the address of the context restore
  400.     | function.
  401.     | It is assumed, that tc_Launch is called via 
  402.     | ... jsr sub
  403.     | ...
  404.     | sub:jsr tc_Launch
  405.     | Thus we have to backup the sp by two jsr's, which is 8.
  406.  
  407. _launch_glue:
  408.     movel    4:w,a0
  409.     movel    a0@(0x114),a0    | tid = SysBase->ThisTask
  410.     movel    a0@(0x36),a0    | usp isn't setup correctly, do it now from tc_SPReg
  411.     movel    sp,a0@-
  412.     addl    #8,a0@
  413.     movel    a4,a0@-
  414.     movel    a0,usp
  415.     
  416.     jsr    _sig_launch    | sig_launch `(void *pc_ret, *ssp_ret)' (`' on usp)
  417.  
  418.     | sig_launch() already corrects the usp to pop those two arguments
  419.     rts
  420.  
  421.  
  422.  
  423. /*
  424.  * update profiling information for the user
  425.  * addupc(pc, &u.u_prof, ticks)
  426.  */
  427. _addupc:
  428.     movl    a2,sp@-            | scratch register
  429.     movl    sp@(12),a2        | get &u.u_prof
  430.     movl    sp@(8),d0        | get user pc
  431.     subl    a2@(8),d0        | pc -= pr->pr_off
  432.     jlt    Lauexit            | less than 0, skip it
  433.     movl    a2@(12),d1        | get pr->pr_scale
  434.     lsrl    #1,d0            | pc /= 2
  435.     lsrl    #1,d1            | scale /= 2
  436.  
  437.     | mulul    d1,d0            | pc /= scale
  438.     moveml    d0/d1,sp@-
  439.     jbsr    ___mulsi3
  440.     lea    sp@(8),sp
  441.  
  442.     moveq    #14,d1
  443.     lsrl    d1,d0            | pc >>= 14
  444.     bclr    #0,d0            | pc &= ~1
  445.     cmpl    a2@(4),d0        | too big for buffer?
  446.     jge    Lauexit            | yes, screw it
  447.     addl    a2@,d0            | no, add base
  448.  
  449.     | movl    d0,sp@-            | push address
  450.     | jbsr    _fusword        | grab old value
  451.     | movl    sp@+,a0            | grab address back
  452.     | cmpl    #-1,d0            | access ok
  453.     | jeq    Lauerror        | no, skip out
  454.  
  455.     movel    d0,a0
  456.     movew    a0@,d0
  457.  
  458.     addw    sp@(18),d0        | add tick to current value
  459.  
  460.     movew    d0,a0@
  461.  
  462.     | movl    d0,sp@-            | push value
  463.     | movl    a0,sp@-            | push address
  464.     | jbsr    _susword        | write back new value
  465.     | addql    #8,sp            | pop params
  466.     | tstl    d0            | fault?
  467.     | jeq    Lauexit            | no, all done
  468. Lauerror:
  469.     | clrl    a2@(12)            | clear scale (turn off prof)
  470. Lauexit:
  471.     movl    sp@+,a2            | restore scratch reg
  472.     rts
  473.  
  474. _resetfpu:
  475.     moveml    a5/a6,sp@-
  476.     lea    pc@(Lreset_fpu),a5
  477.     movel    4:w,a6
  478.     jsr    a6@(-30)        | Supervisor()
  479.     bra    Lafter_reset_fpu
  480.  
  481. Lreset_fpu:
  482.     clrl    sp@-
  483.     frestore sp@+
  484.     rte
  485.  
  486. Lafter_reset_fpu:
  487.     moveml    sp@+,a5/a6
  488.     rts
  489.